1// (c)2013 Felipe Sanches <juca@members.fsf.org>
 2// licensed under the terms of the GNU GPL version 3 (or later)
 3
 4function normalize(v) = v / (sqrt(v[0] * v[0] + v[1] * v[1]));
 5
 6//
 7// The voronoi() function generates a 2D surface, which can be provided to
 8// a) linear_extrude() to produce a 3D object
 9// b) intersection() to restrict it to a a specified shape -- see voronoi_polygon.scad
10//
11// Parameters:
12//   points (required) ... nuclei coordinates (array of [x, y] pairs)
13//   L                 ... the radius of the "world" (the pattern is built within this circle)
14//   thickness         ... the thickness of the lines between cells
15//   round             ... the radius applied to corners (fillet in CAD terms)
16//   nuclei (bool)     ... show nuclei sites
17//
18// These parameters need to be kept more or less in proportion to each other, and to the distance
19// apart of points in the point_set. If one or the other parameter is increased or decreased too
20// much, you'll get no output.
21//
22module voronoi(points, L = 200, thickness = 1, round = 6, nuclei = true) {
23	for (p = points) {
24		difference() {
25			minkowski() {
26				intersection_for(p1 = points){
27					if (p != p1) {
28						angle = 90 + atan2(p[1] - p1[1], p[0] - p1[0]);
29
30						translate((p + p1) / 2 - normalize(p1 - p) * (thickness + round))
31						rotate([0, 0, angle])
32						translate([-L, -L])
33						square([2 * L, L]);
34					}
35				}
36				circle(r = round, $fn = 20);
37			}
38			if (nuclei)
39				translate(p) circle(r = 1, $fn = 20);
40		}
41	}
42}
43
44//
45// The random_voronoi() function is the helper wrapper over the voronoi() core.
46// It generates random nuclei site coordinates into the square area,
47// passing other arguments to voronoi() unchanged.
48//
49// Parameters:
50//   n                 ... number of nuclei sites to be generated
51//   nuclei (bool)     ... show nuclei sites
52//   L                 ... the radius of the "world" (the pattern is built within this circle)
53//   thickness         ... the thickness of the lines between cells
54//   round             ... the radius applied to corners (fillet in CAD terms)
55//   min               ... minimum x and y coordinate for nuclei generation
56//   max               ... maximum x and y coordinate for nuclei generation
57//   seed              ... seed for the random generator (random if undefined)
58//   center (bool)     ... move resulting pattern to [0, 0] if true
59//
60module random_voronoi(n = 20, nuclei = true, L = 200, thickness = 1, round = 6, min = 0, max = 100, seed = undef, center = false) {
61	seed = seed == undef ? rands(0, 100, 1)[0] : seed;
62	echo("Seed", seed);
63
64	// Generate points.
65	x = rands(min, max, n, seed);
66	y = rands(min, max, n, seed + 1);
67	points = [ for (i = [0 : n - 1]) [x[i], y[i]] ];
68        
69	// Center Voronoi.
70	offset_x = center ? -(max(x) - min(x)) / 2 : 0;
71	offset_y = center ? -(max(y) - min(y)) / 2 : 0;
72	translate([offset_x, offset_y])
73    
74	voronoi(points, L = L, thickness = thickness, round = round, nuclei = nuclei);
75}
76
77// example with an explicit list of points:
78point_set = [
79	[0, 0], [30, 0], [20, 10], [50, 20], [15, 30], [85, 30], [35, 30], [12, 60],
80	[45, 50], [80, 80], [20, -40], [-20, 20], [-15, 10], [-15, 50]
81];
82//voronoi(points = point_set, round = 4, nuclei = true);
83
84// example with randomly generated set of points
85random_voronoi(n = 64, round = 6, min = 0, max = 300, seed = 42);